ベンチマークをとろう TypeScript 編
ベンチマークを取ることは非常に重要です。「推測するな、計測せよ」という原則のとおり、複数の実装案が考えられる場合はベンチマークスコアを計測し、最も目的に叶うものを採用しましょう。
これは CX 事業本部の Tech Lead のお仕事紹介第 3 弾の記事です。
TypeScript でのベンチマークスコア計測
benchmark.js を用います。基本的な使い方についてはドキュメントを読んでいただくとして、ここでは TypeScript のサンプルを紹介します。
https://github.com/januswel/benchmark-divide-array-into-chunks
ポイントをいくつか紹介します。
npm スクリプト
誰でも簡単にベンチマークを実行できるようにするため、 npm スクリプトを定義しましょう。
{ // snip "scripts": { "start": "npx ts-node ./index.ts" }, // snip }
ここでは index.ts
を ts-node
を用いて実行しています。
ベンチマークテストを TypeScript で書く
次がベンチマークテストの本体になります。
// ① import * as Benchmark from 'benchmark' // ② import forVersion from './src/for' import reduceVersion from './src/reduce' // ③ const suite = new Benchmark.Suite const src = Array.from({length: 1000}) // ④ suite.add('for version', () => { forVersion(src, 200) }).add('reduce version', () => { reduceVersion(src, 200) }).on('cycle', (event) => { console.log(String(event.target)) }).on('complete', function () { // ⑤ console.log(`Fastest is ${this.filter('fastest').map('name')}`) }) .run({ async: true })
①で benchmark パッケージからもろもろを import
していますが、 @types/benchmark
のインストールが必要です。
②のようにベンチマークスコアを取りたい対象の関数は別途定義しておくと良いでしょう。本体がすっきりとします。
③で一連のベンチマークテストをまとめるためのスイートを生成し、④でどういった処理をテストしたいか、テスト完了後の処理などを指定します。⑤では Arrow Function ではなく function
キーワードを使っていますが、 benchmark.js がベンチマーク結果を this
としてこのコールバック関数を呼び出すからです。
テスト対象の関数
テスト対象の関数はいつもと変わらず定義しましょう。ここでは 2 種類の実装を思いついたので 2 つ書いています。
ベンチマーク結果
yarn start
とうつとベンチマークテストが走ります。
$ yarn start yarn run v1.22.4 $ npx ts-node ./index.ts npx: 8個のパッケージを1.915秒でインストールしました。 for version x 1,267,795 ops/sec ±2.10% (77 runs sampled) reduce version x 277,413 ops/sec ±0.76% (90 runs sampled) Fastest is for version ✨ Done in 15.73s.
for version が 1 秒間に 1,267,795 回の実行が可能と出ています。それに対し、 reduce version は 1 秒あたり 277,413 回の実行が可能というスコアです。
まとめ
今回紹介したコードでは最も速い方法はどれか、という表示もされますが、大幅にスコアが異ならない限り、読みやすさやメンテナンスのしやすさなども考慮してアルゴリズムを選択しましょう。